from flask import Flask, request, jsonify
from flask_cors import CORS
import logging
from pymodbus.client import ModbusSerialClient
from pymodbus.exceptions import ModbusException
from pymodbus.pdu import ExceptionResponse
import time

app = Flask(__name__)
CORS(app)


PORT = '/dev/ttyUSB0'  # Linux
BAUD_RATE = 9600
SLAVE_ID = 1

class ModbusRTUController:
    def __init__(self, port, baudrate=9600, timeout=1):
        """
        初始化Modbus RTU客户端
        :param port: 串口路径 (e.g. '/dev/ttyUSB0' 或 'COM3')
        :param baudrate: 波特率 (默认9600)
        :param timeout: 超时时间(秒) (默认1)
        """
        self.client = ModbusSerialClient(
            port=port,
            baudrate=baudrate,
            timeout=timeout,
            stopbits=1,
            bytesize=8,
            parity='N'
        )
        self.connected = False

    def connect(self):
        """建立串口连接"""
        if not self.connected:
            try:
                self.connected = self.client.connect()
                if self.connected:
                    print(f"成功连接到 {self.client.comm_params.port}")
                else:
                    print("连接失败: 请检查串口配置")
            except Exception as e:
                print(f"连接异常: {str(e)}")
        return self.connected

    def disconnect(self):
        """关闭连接"""
        if self.connected:
            self.client.close()
            self.connected = False
            print("连接已关闭")

    def read_holding_registers(self, slave_id, address, count=1):
        """
        读取保持寄存器
        :param slave_id: 从站地址 (1-247)
        :param address: 寄存器起始地址 (0-65535)
        :param count: 读取数量
        :return: 寄存器值列表 或 None
        """
        if not self.connected:
            print("错误: 未建立连接")
            return None

        try:
            response = self.client.read_holding_registers(
                address=address, 
                count=count, 
                slave=slave_id
            )
            
            if response.isError():
                print(f"Modbus错误: {response}")
                return None
                
            if isinstance(response, ExceptionResponse):
                print(f"异常响应: {response}")
                return None
                
            return response.registers
            
        except ModbusException as e:
            print(f"Modbus通信失败: {str(e)}")
            return None
        except AttributeError as ae:
            print(f"响应解析错误: {str(ae)}")
            return None

    def write_register(self, slave_id, address, value):
        """
        写入单个寄存器
        :param slave_id: 从站地址
        :param address: 寄存器地址
        :param value: 写入值 (0-65535)
        :return: 是否成功
        """
        if not self.connected:
            print("错误: 未建立连接")
            return False

        try:
            response = self.client.write_register(
                address=address,
                value=value,
                slave=slave_id
            )
            
            if response.isError():
                print(f"写入失败: {response}")
                return False
                
            return True
            
        except ModbusException as e:
            print(f"写入异常: {str(e)}")
            return False
    def write_coil(self,channel=1, state=False):
        """
        控制输出通道
        :param channel: 输出通道 (1-48)
        :param state: 开关状态 (True-开启, False-关闭)
        """
        try:
            # 线圈寄存器地址从0开始 (通道1=地址0)
            response = self.client.write_coil(address=channel-1, value=state, slave=SLAVE_ID)
            if not response.isError():
                print(f"通道{channel} {'开启' if state else '关闭'}成功")
                return True
            print(f"控制失败: {response}")
        except ModbusException as e:
            print(f"通信异常: {e}")
        return False
    def write_multiple_registers(self, slave_id, address, values):
        """
        写入多个寄存器
        :param slave_id: 从站地址
        :param address: 起始地址
        :param values: 值列表 (每个值 0-65535)
        :return: 是否成功
        """
        if not self.connected:
            print("错误: 未建立连接")
            return False

        try:
            response = self.client.write_registers(
                address=address,
                values=values,
                slave=slave_id
            )
            
            if response.isError():
                print(f"批量写入失败: {response}")
                return False
                
            return True
            
        except ModbusException as e:
            print(f"批量写入异常: {str(e)}")
            return False

# 使用示例 ======================================================
controller = ModbusRTUController(
    port=PORT,
    baudrate=BAUD_RATE,
    timeout=0.5
)
if controller.connect():
    for i in range(1,21):
        controller.write_coil(i,False)
controller.disconnect()
    
# if __name__ == "__main__":
    # 配置串口参数 (根据实际设备修改)
    # PORT = 'COM3'  # Windows
    # PORT = '/dev/ttyUSB0'  # Linux
    # BAUD_RATE = 9600
    # SLAVE_ID = 1

    # 创建控制器实例
    

    # 建立连接
    
        
        # try:
            

            # # 示例1: 读取保持寄存器
            # print("读取寄存器...")
            # registers = controller.read_holding_registers(
            #     slave_id=SLAVE_ID,
            #     address=0,
            #     count=5
            # )
            # if registers is not None:
            #     print(f"读取结果: {registers}")

            # # 示例2: 写入单个寄存器
            # print("\n写入寄存器...")
            # success = controller.write_register(
            #     slave_id=SLAVE_ID,
            #     address=10,
            #     value=1234
            # )
            # print(f"写入状态: {'成功' if success else '失败'}")

            # # 示例3: 批量写入寄存器
            # print("\n批量写入寄存器...")
            # success = controller.write_multiple_registers(
            #     slave_id=SLAVE_ID,
            #     address=20,
            #     values=[100, 200, 300]
            # )
            # print(f"批量写入状态: {'成功' if success else '失败'}")

            # # 验证写入
            # time.sleep(1)
            # print("\n验证写入结果...")
            # registers = controller.read_holding_registers(
            #     slave_id=SLAVE_ID,
            #     address=20,
            #     count=3
            # )
            # if registers is not None:
            #     print(f"读取结果: {registers}")

        # except KeyboardInterrupt:
        #     print("程序被用户中断")
        # finally:
        #     # 断开连接
        #     controller.disconnect()

def update_window(data,index1,index2):
    if data == "up":
        controller.write_coil(index1,True)
        controller.write_coil(index2,False)
    elif data == "down":
        controller.write_coil(index1,False)
        controller.write_coil(index2,True)
    else:
        controller.write_coil(index1,False)
        controller.write_coil(index2,False)

@app.route('/receive_data', methods=['POST'])
def receive_data():
    # 获取 JSON 数据
    data = request.get_json()
    
    # 如果需要获取表单数据，可以使用 request.form
    # data = request.form.to_dict()

    # 处理数据（这里只是简单地返回接收到的数据）
    response = {
        'status': 'success',
        'received_data': data
    }
    print(data)
    # switch_status:{
    #     top_window:false,
    #     left_f_window:false,
    #     left_r_window:false,
    #     right_f_window:false,
    #     right_r_window:false,
    #     info:false,
    #     headlights:false,
    #     motor:false,
    #     colorlights:false,
    #     power:false,
    #     showInfoPanel:false,
    #   },

    # 创建控制器实例
    

    if controller.connect():

        # 电机
        controller.write_coil(17,data['motor'])
        # 彩灯
        controller.write_coil(18,data['colorlights'])
        # 大灯
        controller.write_coil(19,data['headlights'])
        # 天窗
        update_window(data['top_window'],1,2)
        # 左前窗
        update_window(data['left_f_window'],3,4)
        # 左后窗
        update_window(data['left_r_window'],5,6)
        # 右前窗
        update_window(data['right_f_window'],7,13)
        # 右后窗
        update_window(data['right_r_window'],14,15)

    controller.disconnect()

    return jsonify(response)




if __name__ == '__main__':
    app.run(host='0.0.0.0', port=5000, debug=True,threaded=False)



